/*
 *  Copyright (c) 2010 Stephen Nelson <stephen@sfnelson.org>
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *  THE SOFTWARE.
 */

package org.sfnelson.bma.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

public class UseExistingPanel extends Composite implements AsyncCallback<UserData> {

	private static UseExistingPanelUiBinder uiBinder = GWT.create(UseExistingPanelUiBinder.class);

	interface UseExistingPanelUiBinder extends UiBinder<Widget, UseExistingPanel> {
	}

	interface Style extends CssResource {
		String error();

		String init();

		String ready();
	}

	private static final String INVALID = "invalid";
	private static final String READY = "ready";
	private static final String SETTING = "saving";
	private static final String DEFAULT_SERIAL = "US-0000-0000-0000";
	private static final String DEFAULT_CODE = "0000000000";

	private KeyServiceAsync service;
	private Bma parent;

	@UiField
	Style style;
	@UiField
	TextBox serial;
	@UiField
	TextBox code;
	@UiField
	Anchor submit;

	public UseExistingPanel(KeyServiceAsync service, Bma parent) {
		initWidget(uiBinder.createAndBindUi(this));

		this.service = service;
		this.parent = parent;

		code.setText(DEFAULT_CODE);
		serial.setText(DEFAULT_SERIAL);
		submit.setText(INVALID);

		validate();
	}

	@UiHandler("serial")
	void serialKeyUp(KeyUpEvent ev) {
		validate();

		if (ev.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
			submitOnClick(null);
		}
	}

	@UiHandler("code")
	void secretKeyUp(KeyUpEvent ev) {
		validate();

		if (ev.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
			submitOnClick(null);
		}
	}

	@UiHandler("code")
	void secretOnFocus(FocusEvent ev) {
		if (code.getText().equals(DEFAULT_CODE)) {
			code.setText("");
		}
	}

	@UiHandler("serial")
	void serialOnFocus(FocusEvent ev) {
		if (serial.getText().equals(DEFAULT_SERIAL)) {
			serial.setText("");
		}
	}

	@UiHandler("code")
	void secretOnBlur(BlurEvent ev) {
		if (code.getText().equals("")) {
			code.setText(DEFAULT_CODE);
		}

		validate();
	}

	@UiHandler("serial")
	void serialOnBlur(BlurEvent ev) {
		if (serial.getText().equals("")) {
			serial.setText(DEFAULT_SERIAL);
		}

		validate();
	}

	@UiHandler("submit")
	void submitOnClick(ClickEvent ev) {
		if (validate()) {
			service.retrieveSecret(serial.getText(), code.getText(), this);
			submit.setText(SETTING);
		}
	}

	public boolean validate() {
		boolean ok = true;

		if (validateSerial()) {
			serial.removeStyleName(style.error());
		} else {
			ok = false;
			serial.addStyleName(style.error());
		}

		if (serial.getText().equals(DEFAULT_SERIAL)) {
			serial.addStyleName(style.init());
			ok = false;
		} else {
			serial.removeStyleName(style.init());
		}

		if (validateSecret()) {
			code.removeStyleName(style.error());
		} else {
			ok = false;
			code.addStyleName(style.error());
		}

		if (code.getText().equals(DEFAULT_CODE)) {
			code.addStyleName(style.init());
			ok = false;
		} else {
			code.removeStyleName(style.init());
		}

		if (ok) {
			submit.addStyleName(style.ready());
			submit.setText(READY);
		} else {
			submit.removeStyleName(style.ready());
			submit.setText(INVALID);
		}

		return ok;
	}

	private boolean validateSerial() {
		return serial.getText().matches("^(US|KR|EU)-[0-9]{4}-[0-9]{4}-[0-9]{4}$");
	}

	private boolean validateSecret() {
		return code.getText().matches("^[0123456789ABCDEFGHJKLMNPQRTUVWXYZ]{10}$");
	}

	public void onFailure(Throwable caught) {
		ErrorConsole.addMessage("Unable to save keys", caught);
		validate();
	}

	public void onSuccess(UserData result) {
		removeFromParent();
		parent.showKey(result);
	}
}
